// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "Cosmetics/LyraCosmeticAnimationTypes.h"
#include "Equipment/LyraEquipmentInstance.h"
#include "GameFramework/InputDevicePropertyHandle.h"

#include "LyraWeaponInstance.generated.h"

// 定义API宏
#define UE_API LYRAGAME_API

class UAnimInstance;
class UObject;
struct FFrame;
struct FGameplayTagContainer;
class UInputDeviceProperty;

/**
 * ULyraWeaponInstance
 * 代表武器的装备实例，生成并应用于Pawn
 */
UCLASS(MinimalAPI)
class ULyraWeaponInstance : public ULyraEquipmentInstance
{
	GENERATED_BODY()

public:
	// 构造函数
	UE_API ULyraWeaponInstance(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());

	//~ULyraEquipmentInstance 接口
	/**
	 * 重写的装备接口。装备时调用。
	 */
	UE_API virtual void OnEquipped() override;
	/**
	 * 重写的装备接口。卸下时调用。
	 */
	UE_API virtual void OnUnequipped() override;
	//~End of ULyraEquipmentInstance 接口

	/**
	 * 更新开火时间。
	 */
	UFUNCTION(BlueprintCallable)
	UE_API void UpdateFiringTime();

	/**
	 * 返回自上次与武器交互（开火或装备）以来经过的时间。
	 * @return 返回经过的时间（秒）
	 */
	UFUNCTION(BlueprintPure)
	UE_API float GetTimeSinceLastInteractedWith() const;

protected:
	// 装备时的动画层选择集
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Animation)
	FLyraAnimLayerSelectionSet EquippedAnimSet;

	// 卸下时的动画层选择集
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category=Animation)
	FLyraAnimLayerSelectionSet UneuippedAnimSet; // 注意：拼写错误，应为Unequipped

	/**
	 * 装备此武器时应应用的输入设备属性。
	 * 这些属性将以"循环"标志启用播放，因此它们将持续播放直到武器被卸下！
	 */
	UPROPERTY(EditDefaultsOnly, Instanced, BlueprintReadOnly, Category = "Input Devices")
	TArray<TObjectPtr<UInputDeviceProperty>> ApplicableDeviceProperties;
	
	/**
	 * 根据指定的游戏标签从EquippedAnimSet或UneuippedAnimSet中选择最佳动画层。
	 * @param bEquipped 是否装备
	 * @param CosmeticTags 装饰性标签容器
	 * @return 返回动画实例类
	 */
	UFUNCTION(BlueprintCallable, BlueprintPure=false, Category=Animation)
	UE_API TSubclassOf<UAnimInstance> PickBestAnimLayer(bool bEquipped, const FGameplayTagContainer& CosmeticTags) const;

	/** 返回拥有此武器的Pawn的平台用户ID */
	UFUNCTION(BlueprintCallable)
	UE_API const FPlatformUserId GetOwningUserId() const;

	/** 当此武器的拥有Pawn死亡时的回调。移除所有生成的设备属性。 */
	UFUNCTION()
	UE_API void OnDeathStarted(AActor* OwningActor);

	/**
	 * 将ApplicableDeviceProperties应用到此武器的拥有Pawn。
	 * 填充DevicePropertyHandles以便以后可以移除。这将
	 * 以循环模式播放设备属性，因此它们将与武器装备的生命周期共享。
	 */
	UE_API void ApplyDeviceProperties();

	/** 移除在ApplyDeviceProperties中激活的任何设备属性。 */
	UE_API void RemoveDeviceProperties();

private:
	/** 由此武器激活的设备属性集合。由ApplyDeviceProperties填充 */
	UPROPERTY(Transient)
	TSet<FInputDevicePropertyHandle> DevicePropertyHandles;

	// 最后装备时间
	double TimeLastEquipped = 0.0;
	// 最后开火时间
	double TimeLastFired = 0.0;
};

// 取消定义API宏
#undef UE_API